package com.xyht.sca_s.student_manage_system.modules.asset.service.impl;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.req.*;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.resp.*;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.resp.fixedInStorageApply.SmsAssetFixedInStorageApplyResp;
import org.springframework.core.io.ClassPathResource;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.ApiModelUtil;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.*;
import com.xyht.sca_s.student_manage_system.modules.asset.mapper.*;
import com.xyht.sca_s.student_manage_system.modules.asset.service.SmsAssetMaterialProcurementApplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.modules.asset.util.AssetUtil;
import com.xyht.sca_s.student_manage_system.modules.assetConsumable.entity.*;
import com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.entity.resp.SmsSearchUserResp;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetAllowTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetBooleanConstant.ASSET_BOOLEAN_FALSE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetBooleanConstant.ASSET_BOOLEAN_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetObjectTypeConstant.ASSET_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetProcessTypeConstant.ASSET_PROCESS_TYPE_MATERIAL_PROCUREMENT;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.CommonConstant.EXAMINE_STATUS_PASS;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.CommonConstant.EXAMINE_STATUS_WAIT_ALLOW;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.ProcessObjectTypeConstant.PROCESS_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.assetConsumable.constant.AssetAllowStatusConstant.*;

/**
 * <p>
 * 物资采购申请单 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-09-19
 */
@Service
public class SmsAssetMaterialProcurementApplyServiceImpl extends ServiceImpl<SmsAssetMaterialProcurementApplyMapper, SmsAssetMaterialProcurementApply> implements SmsAssetMaterialProcurementApplyService {

    @Resource
    private SmsAssetProcessMapper smsAssetProcessMapper;
    @Resource
    private SmsAssetProcessDetailMapper smsAssetProcessDetailMapper;
    @Resource
    private SmsAssetCategoryManagementMapper smsAssetCategoryManagementMapper;
    @Resource
    private NewTipsUtil newTipsUtil;
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private AssetUtil assetUtil;
    @Resource
    private SmsUserMapper smsUserMapper;
    @Resource
    private ApiModelUtil apiModelUtil;
    @Resource
    private SmsRoleMapper smsRoleMapper;
    @Resource
    private FileSavePathConstant fileSavePathConstant;
    @Resource
    private SmsAssetMaterialProcurementApplyMapper smsAssetMaterialProcurementApplyMapper;
    @Resource
    private SmsAssetMaterialProcurementApplyGoodsMapper smsAssetMaterialProcurementApplyGoodsMapper;
    @Resource
    private SmsAssetMaterialProcurementApplyProcessDetailMapper smsAssetMaterialProcurementApplyProcessDetailMapper;
    @Resource
    private SmsAssetMaterialProcurementApplyProcessDetailMPJMapper smsAssetMaterialProcurementApplyProcessDetailMPJMapper;

    @Override
    @Transactional
    public ResponseResult addMaterialProcurementApply(SmsAssetMaterialProcurementApplyReq req, String userId) {
        //校验前端传入参数
        if (isNullOrEmpty(req.getApplyPerson()) || isNullOrEmpty(req.getGoodsList()) || req.getGoodsList().size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }


        //查询系统节点并判断是否合法
        SmsAssetProcess originProcess = smsAssetProcessMapper.selectOne(new LambdaQueryWrapper<SmsAssetProcess>()
                .eq(SmsAssetProcess::getProcessType, ASSET_PROCESS_TYPE_MATERIAL_PROCUREMENT));
        if (originProcess == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_PROCESS_NOT_SETTING));
        }
        //查询节点流程进行匹配,判断申请人是否设置完所有流程
        List<SmsAssetProcessDetail> systemProcessList = smsAssetProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsAssetProcessDetail>()
                .eq(SmsAssetProcessDetail::getProcessDetailIsApplicantEdit, ASSET_BOOLEAN_TRUE)
                .eq(SmsAssetProcessDetail::getProcessDetailIsUse, ASSET_BOOLEAN_TRUE)
                .eq(SmsAssetProcessDetail::getProcessId, originProcess.getId())
                .orderByAsc(SmsAssetProcessDetail::getProcessDetailSort));
        if (systemProcessList != null && systemProcessList.size() > 0) {
            if (req.getProcessList() == null || req.getProcessList().size() < 1) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_USER_NOT_SETTING);
            }
            //判断申请人是否将全部需要编辑的流程填写完毕
            List<SmsAssetProcessDetail> filterList = systemProcessList.stream().filter(systemProcess -> {
                        //匹配的去除,未匹配的留下
                        List<SmsAssetMaterialProcurementApplyProcessDetailReq> result = req.getProcessList().stream()
                                .filter(applyProcess -> applyProcess.getProcessDetailId().equals(systemProcess.getId()))
                                .collect(Collectors.toList());
                        //如果全部匹配,则 result.size() = 0
                        return result.size() == 0;
                    }
            ).collect(Collectors.toList());
            if (filterList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_PROCESS_NOT_FILL);
            }
        }

        //创建申请表
        SmsAssetMaterialProcurementApply smsAssetMaterialProcurementApply = new SmsAssetMaterialProcurementApply();
        BeanUtils.copyProperties(req, smsAssetMaterialProcurementApply);
        smsAssetMaterialProcurementApply.setApplyUserId(userId);
        smsAssetMaterialProcurementApply.setAllowStatus(ASSET_ALLOW_STATUS_WAIT_ALLOW);
        smsAssetMaterialProcurementApply.setApplyDate(new Date());
        smsAssetMaterialProcurementApplyMapper.insert(smsAssetMaterialProcurementApply);
        //判断是否插入成功
        String applyId = smsAssetMaterialProcurementApply.getId();
        if (applyId == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        //创建物资采购申请物品记录
        for (SmsAssetMaterialProcurementApplyGoodsReq goodsReq : req.getGoodsList()) {
            //校验物品是否正常传入
            if (isNullOrEmpty(goodsReq.getMaterialName()) || isNullOrEmpty(goodsReq.getMaterialModel())
                    || isNullOrEmpty(goodsReq.getMaterialUnit()) || isNullOrEmpty(goodsReq.getMaterialPlanNum())
                    || isNullOrEmpty(goodsReq.getMaterialRealNum()) || isNullOrEmpty(goodsReq.getMaterialUse())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
       /*     //校验分类是否合法
            SmsAssetCategoryManagement assetCategoryManagement = smsAssetCategoryManagementMapper.selectById(goodsReq.getAssetCategory());
            if (assetCategoryManagement == null || isNullOrEmpty(assetCategoryManagement.getId())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_NOT_EXIST));
            }
            //判断是否为根类别
            if (assetCategoryManagement.getId().length() < 3) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_CAN_NOT_USE_ROOT));
            }*/
            //判断数量
            if (goodsReq.getMaterialPlanNum() <= 0 || goodsReq.getMaterialRealNum() <= 0) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_STORAGE_NUM_ERR));
            }

            SmsAssetMaterialProcurementApplyGoods smsAssetMaterialProcurementApplyGoods = new SmsAssetMaterialProcurementApplyGoods();
            BeanUtils.copyProperties(goodsReq, smsAssetMaterialProcurementApplyGoods);
            smsAssetMaterialProcurementApplyGoods.setApplyId(applyId);
            smsAssetMaterialProcurementApplyGoodsMapper.insert(smsAssetMaterialProcurementApplyGoods);
        }

        //创建审批流程
        //查询系统流程节点
        List<SmsAssetProcessDetail> systemProcessDetailList = smsAssetProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsAssetProcessDetail>()
                .eq(SmsAssetProcessDetail::getProcessDetailIsUse, ASSET_BOOLEAN_TRUE)
                .eq(SmsAssetProcessDetail::getProcessId, originProcess.getId())
                .orderByAsc(SmsAssetProcessDetail::getProcessDetailSort));
        if (systemProcessDetailList == null || systemProcessDetailList.size() < 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsAssetProcessDetail process : systemProcessDetailList) {
            //判断管理员是否配置初始流程
            if (process.getProcessDetailIsApplicantEdit().equals(ASSET_BOOLEAN_FALSE)) {
                if (isNullOrEmpty(process.getProcessDetailObjectId()) || isNullOrEmpty(process.getProcessDetailObjectType())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_PROCESS_NOT_SETTING));
                }
            }

            SmsAssetMaterialProcurementApplyProcessDetail addDetail = new SmsAssetMaterialProcurementApplyProcessDetail();
            addDetail.setApplyId(applyId);
            addDetail.setProcessDetailId(process.getId());
            addDetail.setProcessDetailIsSign(process.getProcessDetailIsSign());
            addDetail.setProcessDetailIsStamp(process.getProcessDetailIsStamp());
            addDetail.setProcessDetailName(process.getProcessDetailName());
            addDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_WAIT_ALLOW);
            addDetail.setProcessDetailSort(sort++);

            //申请人可编辑流程
            if (process.getProcessDetailIsApplicantEdit().equals(ASSET_BOOLEAN_TRUE)) {
                List<SmsAssetMaterialProcurementApplyProcessDetailReq> filterList = req.getProcessList().stream()
                        .filter(applyProcess -> applyProcess.getProcessDetailId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterList.size() == 0) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_PROCESS_NOT_FILL));
                }
                SmsAssetMaterialProcurementApplyProcessDetailReq filterProcessReq = filterList.get(0);
                if (isNullOrEmpty(filterProcessReq.getProcessDetailObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                addDetail.setProcessDetailObjectId(filterProcessReq.getProcessDetailObjectId());
                addDetail.setProcessDetailObjectType(ASSET_OBJECT_TYPE_PERSON);
            } else {
                addDetail.setProcessDetailObjectId(process.getProcessDetailObjectId());
                addDetail.setProcessDetailObjectType(process.getProcessDetailObjectType());
            }
            smsAssetMaterialProcurementApplyProcessDetailMapper.insert(addDetail);
        }

        //消息通知
        //通知流程第一个节点
        SmsAssetMaterialProcurementApplyProcessDetail firstDetail =
                smsAssetMaterialProcurementApplyProcessDetailMapper.selectOne(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                        .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, applyId)
                        .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailSort, 1)
                        .orderByAsc(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            if (firstDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
        }

        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessDetailObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                userId,
                rangeTypeEnum,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_ASSET_MATERIAL_PROCUREMENT,
                applyId,
                firstDetail.getId());

        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult cancelMaterialProcurementApply(SmsAssetMaterialProcurementApplyReq cancelReq, String userId) {
        //校验前端参数
        if (isNullOrEmpty(cancelReq.getApplyId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //根据id获取申请表并校验
        SmsAssetMaterialProcurementApply assetApply = smsAssetMaterialProcurementApplyMapper.selectOne(new LambdaQueryWrapper<SmsAssetMaterialProcurementApply>()
                .eq(SmsAssetMaterialProcurementApply::getApplyUserId, userId)
                .eq(SmsAssetMaterialProcurementApply::getId, cancelReq.getApplyId()));
        if (assetApply == null) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        //若非待审批状态不可撤回
        if (assetApply.getAllowStatus() != EXAMINE_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.ASSET_CANCEL_FAIL_ALLOWED);
        }

        //判断是否审批中
        List<SmsAssetMaterialProcurementApplyProcessDetail> detailList =
                smsAssetMaterialProcurementApplyProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                        .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, cancelReq.getApplyId())
                        .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailStatus, EXAMINE_STATUS_PASS));
        if (detailList != null && detailList.size() > 0) {
            return CommonResult.failed(CommonCodeEnum.ASSET_CANCEL_FAIL_ALLOWING);
        }

        //撤回审批
        SmsAssetMaterialProcurementApply cancelApply = new SmsAssetMaterialProcurementApply();
        cancelApply.setId(cancelReq.getApplyId());
        cancelApply.setAllowStatus(ASSET_ALLOW_STATUS_CANCEL);
        cancelApply.setEndTime(new Date());
        smsAssetMaterialProcurementApplyMapper.updateById(cancelApply);

        //修改节点状态
        SmsAssetMaterialProcurementApplyProcessDetail cancelProcessDetail = new SmsAssetMaterialProcurementApplyProcessDetail();
        cancelProcessDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_CANCEL);

        smsAssetMaterialProcurementApplyProcessDetailMapper.update(cancelProcessDetail, new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, cancelReq.getApplyId()));

        //消息通知
        newTipsUtil.cancelFinishTips(cancelReq.getApplyId());
        return CommonResult.success();
    }

    @Override
    public ResponseResult getMaterialProcurementApplyList(String userId, Integer applyType, Integer pageNum, Integer pageSize) {
        //校验前端参数
        if (isNullOrEmpty(applyType)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //构造回传数据
        List<SmsAssetMaterialProcurementApplyResp> respList = new ArrayList<>();
        int total = 0;

        //根据applyType进行相关处理
        if (applyType == ASSET_ALLOW_TYPE_APPLY) {//已发起
            Page<SmsAssetMaterialProcurementApply> page = new Page<>(pageNum, pageSize);
            LambdaQueryWrapper<SmsAssetMaterialProcurementApply> queryWrapper = new LambdaQueryWrapper<SmsAssetMaterialProcurementApply>()
                    .eq(SmsAssetMaterialProcurementApply::getApplyUserId, userId)
                    .orderByDesc(SmsAssetMaterialProcurementApply::getCreateTime);
            smsAssetMaterialProcurementApplyMapper.selectPage(page, queryWrapper);
            respList = page.getRecords().stream().map(apply -> {
                SmsAssetMaterialProcurementApplyResp applyResp = new SmsAssetMaterialProcurementApplyResp();
                BeanUtils.copyProperties(apply, applyResp);
                applyResp.setId(apply.getId());
                //获取当前用户信息并进行设置
                SmsUser smsUser = cacheUtil.getUserInfo(apply.getApplyUserId());
                SmsSearchUserResp userResp = new SmsSearchUserResp();
                if (smsUser != null) {
                    BeanUtils.copyProperties(smsUser, userResp);
                }
                applyResp.setApplyUserInfo(userResp);
                return applyResp;
            }).collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (applyType == ASSET_ALLOW_TYPE_ALLOWED) {//已办
            Page<SmsAssetMaterialProcurementApplyMpjResp> page = new Page<>(pageNum, pageSize);
            MPJLambdaWrapper<SmsAssetMaterialProcurementApplyProcessDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectAll(SmsAssetMaterialProcurementApplyProcessDetail.class).selectAll(SmsAssetMaterialProcurementApply.class)
                    .selectAs(SmsAssetMaterialProcurementApply::getCreateTime, "applyCreateTime")
                    .selectAs(SmsAssetMaterialProcurementApplyProcessDetail::getId, "detailId")
                    .leftJoin(SmsAssetMaterialProcurementApply.class, SmsAssetMaterialProcurementApply::getId, SmsAssetMaterialProcurementApplyProcessDetail::getApplyId)
                    .eq(SmsAssetMaterialProcurementApplyProcessDetail::getAllowUserId, userId)
                    .orderByDesc(SmsAssetMaterialProcurementApply::getCreateTime)
                    .orderByDesc(SmsAssetMaterialProcurementApplyProcessDetail::getEndTime);
            smsAssetMaterialProcurementApplyProcessDetailMPJMapper.selectJoinPage(page, SmsAssetMaterialProcurementApplyMpjResp.class, mpjLambdaWrapper);

            respList = page.getRecords().stream()
                    .map(smsMPJResp -> {
                        SmsAssetMaterialProcurementApplyResp applyResp = new SmsAssetMaterialProcurementApplyResp();
                        BeanUtils.copyProperties(smsMPJResp, applyResp);
                        applyResp.setCreateTime(smsMPJResp.getApplyCreateTime());
                        applyResp.setEndTime(smsMPJResp.getApplyEndTime());
                        applyResp.setId(smsMPJResp.getApplyId());

                        SmsUser applyUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
                        SmsSearchUserResp applyUserResp = new SmsSearchUserResp();
                        if (applyUser != null) {
                            BeanUtils.copyProperties(applyUser, applyUserResp);
                        }
                        applyResp.setApplyUserInfo(applyUserResp);

                        SmsUser allowUser = cacheUtil.getUserInfo(applyResp.getAllowUserId());
                        SmsSearchUserResp allowUserResp = new SmsSearchUserResp();
                        if (allowUser != null) {
                            BeanUtils.copyProperties(allowUser, allowUserResp);
                        }
                        applyResp.setAllowUserInfo(allowUserResp);
                        return applyResp;
                    }).collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (applyType == ASSET_ALLOW_TYPE_WAIT_ALLOW) {//待办
            List<String> roleList = cacheUtil.getRoleList(userId);

            //获取所有待审批申请流程节点
            List<SmsAssetMaterialProcurementApplyProcessDetail> allDetailList =
                    smsAssetMaterialProcurementApplyProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                            .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));

            List<SmsAssetMaterialProcurementApplyProcessDetail> filterDetailList = allDetailList.stream().filter(detail -> {
                if (detail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
                    if (!detail.getProcessDetailObjectId().equals(userId)) {
                        return false;
                    }
                } else {
                    if (detail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                        if (!detail.getProcessDetailObjectId().equals(userId)) {
                            return false;
                        }
                    } else {
                        List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessDetailObjectId())).collect(Collectors.toList());
                        if (filterRoleList.size() < 1) {
                            return false;
                        }
                    }
                }

                if (detail.getProcessDetailSort().equals(1)) {
                    return true;
                }

                //判断上一个流程节点是否完成
                SmsAssetMaterialProcurementApplyProcessDetail preDetail =
                        smsAssetMaterialProcurementApplyProcessDetailMapper.selectOne(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                                .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, detail.getApplyId())
                                .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailSort, detail.getProcessDetailSort() - 1)
                                .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_PASS));
                if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                    return false;
                }
                return true;
            }).collect(Collectors.toList());

            if (filterDetailList.size() > 0) {//获取到当前用户待审批节点集合
                List<String> detailIDList = filterDetailList.stream().map(SmsAssetMaterialProcurementApplyProcessDetail::getId).collect(Collectors.toList());
                Page<SmsAssetMaterialProcurementApplyMpjResp> page = new Page<>(pageNum, pageSize);
                MPJLambdaWrapper<SmsAssetMaterialProcurementApplyProcessDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
                mpjLambdaWrapper.selectAll(SmsAssetMaterialProcurementApplyProcessDetail.class).selectAll(SmsAssetMaterialProcurementApply.class)
                        .selectAs(SmsAssetMaterialProcurementApply::getCreateTime, "applyCreateTime")
                        .selectAs(SmsAssetMaterialProcurementApplyProcessDetail::getId, "detailId")
                        .leftJoin(SmsAssetMaterialProcurementApply.class, SmsAssetMaterialProcurementApply::getId, SmsAssetMaterialProcurementApplyProcessDetail::getApplyId)
                        .in(SmsAssetMaterialProcurementApplyProcessDetail::getId, detailIDList)
                        .orderByDesc(SmsAssetMaterialProcurementApply::getCreateTime)
                        .orderByDesc(SmsAssetMaterialProcurementApplyProcessDetail::getCreateTime);
                smsAssetMaterialProcurementApplyProcessDetailMPJMapper.selectJoinPage(page, SmsAssetMaterialProcurementApplyMpjResp.class, mpjLambdaWrapper);

                respList = page.getRecords().stream()
                        .map(smsApplyMPJResp -> {
                            SmsAssetMaterialProcurementApplyResp applyResp = new SmsAssetMaterialProcurementApplyResp();
                            BeanUtils.copyProperties(smsApplyMPJResp, applyResp);
                            applyResp.setCreateTime(smsApplyMPJResp.getApplyCreateTime());
                            applyResp.setId(smsApplyMPJResp.getApplyId());

                            SmsUser applyUser = cacheUtil.getUserInfo(smsApplyMPJResp.getApplyUserId());
                            SmsSearchUserResp smsExamineUserResp = new SmsSearchUserResp();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, smsExamineUserResp);
                            }
                            applyResp.setApplyUserInfo(smsExamineUserResp);
                            return applyResp;
                        }).collect(Collectors.toList());
                total = (int) page.getTotal();
            }
        }
        return CommonResult.success(respList, total);
    }

    @Override
    public ResponseResult getMaterialProcurementApplyDetail(String applyId, String userId) {
        if (isNullOrEmpty(applyId)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsAssetMaterialProcurementApply assetApply = smsAssetMaterialProcurementApplyMapper.selectById(applyId);
        if (assetApply == null || isNullOrEmpty(assetApply.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        SmsAssetMaterialProcurementApplyResp applyResp = new SmsAssetMaterialProcurementApplyResp();
        BeanUtils.copyProperties(assetApply, applyResp);

        SmsUser smsUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
        SmsSearchUserResp smsUserResp = new SmsSearchUserResp();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, smsUserResp);
        }
        applyResp.setApplyUserInfo(smsUserResp);

        //封装流程节点
        List<SmsAssetMaterialProcurementApplyProcessDetailResp> detailRespList =
                smsAssetMaterialProcurementApplyProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                                .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, applyId)
                                .orderByAsc(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailSort))
                        .stream()
                        .map(detail -> {
                            SmsAssetMaterialProcurementApplyProcessDetailResp detailResp = new SmsAssetMaterialProcurementApplyProcessDetailResp();
                            BeanUtils.copyProperties(detail, detailResp);
                            //如果有审批人,对审批人进行封装
                            if (!isNullOrEmpty(detailResp.getAllowUserId())) {
                                SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getAllowUserId());
                                SmsSearchUserResp smsSearchUserResp = new SmsSearchUserResp();
                                if (userInfo != null) {
                                    BeanUtils.copyProperties(userInfo, smsSearchUserResp);
                                }
                                detailResp.setAllowUserInfo(smsSearchUserResp);
                            }
                            if(detail.getProcessDetailObjectType() == PROCESS_OBJECT_TYPE_PERSON){
                                SmsUser allowUser = cacheUtil.getUserInfo(detail.getProcessDetailObjectId());
                                if(allowUser != null) {
                                    detailResp.setObjectName(allowUser.getRealName());
                                    detailResp.setObjectPic(allowUser.getUserPic());
                                }
                            }else {
                                SmsRole smsRole = smsRoleMapper.selectById(detail.getProcessDetailObjectId());
                                if(smsRole != null) {
                                    detailResp.setObjectName(smsRole.getRoleName());
                                }
                            }
                            return detailResp;
                        }).collect(Collectors.toList());
        applyResp.setProcessList(detailRespList);

        //封装物品信息
        List<SmsAssetMaterialProcurementApplyGoodsResp> goodsList =
                smsAssetMaterialProcurementApplyGoodsMapper.selectList(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyGoods>()
                                .eq(SmsAssetMaterialProcurementApplyGoods::getApplyId, applyId))
                        .stream().map(goods -> {
                            SmsAssetMaterialProcurementApplyGoodsResp goodsResp = new SmsAssetMaterialProcurementApplyGoodsResp();
                            BeanUtils.copyProperties(goods, goodsResp);

//                            SmsAssetCategoryManagement categoryManagement = smsAssetCategoryManagementMapper.selectById(goods.getAssetCategory());
//                            if (categoryManagement != null) {
//                                goodsResp.setAssetCategory(categoryManagement.getCategoryName());
//                            }
                            return goodsResp;
                        }).collect(Collectors.toList());
        applyResp.setGoodsList(goodsList);
        return CommonResult.success(applyResp);
    }

    @Override
    @Transactional
    public ResponseResult allowMaterialProcurementApply(SmsAssetMaterialProcurementApplyAllowReq allowReq, String userId) {
        //校验前端参数
        if (isNullOrEmpty(allowReq.getApplyId()) || isNullOrEmpty(allowReq.getDetailId()) || isNullOrEmpty(allowReq.getProcessDetailStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }



        //若传入参数非“通过”且非“驳回”,进行阻断
        if (allowReq.getProcessDetailStatus() != ASSET_ALLOW_STATUS_PASS && allowReq.getProcessDetailStatus() != ASSET_ALLOW_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //校验申请表是否存在
        SmsAssetMaterialProcurementApply smsAssetMaterialProcurementApply = smsAssetMaterialProcurementApplyMapper.selectById(allowReq.getApplyId());
        if (smsAssetMaterialProcurementApply == null || isNullOrEmpty(smsAssetMaterialProcurementApply.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        //校验该节点是否为“待审批”状态
        SmsAssetMaterialProcurementApplyProcessDetail processDetail =
                smsAssetMaterialProcurementApplyProcessDetailMapper.selectOne(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                        .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, allowReq.getApplyId())
                        .eq(SmsAssetMaterialProcurementApplyProcessDetail::getId, allowReq.getDetailId())
                        .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        if (processDetail == null || isNullOrEmpty(processDetail.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
        }

        //判断该节点是否本人审批(防止跳节点审批)
        if (processDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
            if (!processDetail.getProcessDetailObjectId().equals(userId)) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
            }
        } else {
            List<String> roleList = cacheUtil.getRoleList(userId);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(processDetail.getProcessDetailObjectId())).collect(Collectors.toList());
            if (filterRoleList.size() < 1) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
            }
        }

        //校验上一个节点状态是否为“通过”
        if (!processDetail.getProcessDetailSort().equals(1)) {
            SmsAssetMaterialProcurementApplyProcessDetail preDetail =
                    smsAssetMaterialProcurementApplyProcessDetailMapper.selectOne(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                            .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, allowReq.getApplyId())
                            .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailSort, processDetail.getProcessDetailSort() - 1));
            if (preDetail != null && isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getProcessDetailStatus() != ASSET_ALLOW_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
                }
            }
        }

        //审批为通过时才填
        if(allowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS){
            //校验审批数量
            List<SmsAssetMaterialProcurementApplyAllowDetailReq> applyAllowDetailList = allowReq.getApplyAllowDetailList();
            if (applyAllowDetailList == null || applyAllowDetailList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            //修改goods物品表
            for (SmsAssetMaterialProcurementApplyAllowDetailReq allowDetailReq : applyAllowDetailList) {
                if (isNullOrEmpty(allowDetailReq.getApplyNum())|| allowDetailReq.getApplyNum() < 0
                        || isNullOrEmpty(allowDetailReq.getId())) {
                    return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
                }
                SmsAssetMaterialProcurementApplyGoods goods = smsAssetMaterialProcurementApplyGoodsMapper.selectById(allowDetailReq.getId());
                if (isNullOrEmpty(goods)) {
                    return CommonResult.failed(CommonCodeEnum.GOODS_NOT_EXIST);
                }
                goods.setMaterialRealNum(allowDetailReq.getApplyNum());
                smsAssetMaterialProcurementApplyGoodsMapper.updateById(goods);
            }
        }

        //修改ProcessDetail节点表
        SmsAssetMaterialProcurementApplyProcessDetail allowDetail = new SmsAssetMaterialProcurementApplyProcessDetail();
        allowDetail.setId(allowReq.getDetailId());
        allowDetail.setProcessDetailStatus(allowReq.getProcessDetailStatus());
        if (!isNullOrEmpty(allowReq.getProcessDetailRemark())) {
            allowDetail.setProcessDetailRemark(allowReq.getProcessDetailRemark());
        }
        Date nowDate = new Date();
        allowDetail.setEndTime(nowDate);
        allowDetail.setAllowUserId(userId);
        //设置签名
        if (processDetail.getProcessDetailIsSign() == ASSET_BOOLEAN_TRUE) {
            if (isNullOrEmpty(allowReq.getProcessDetailSign())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            allowDetail.setProcessDetailSign(allowReq.getProcessDetailSign());
        }
        //设置印章
        if (processDetail.getProcessDetailIsStamp() == ASSET_BOOLEAN_TRUE) {
            if (isNullOrEmpty(allowReq.getProcessDetailStamp())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            allowDetail.setProcessDetailStamp(allowReq.getProcessDetailStamp());
        }
        smsAssetMaterialProcurementApplyProcessDetailMapper.updateById(allowDetail);


        //流程是否结束标志
        boolean is_done = false;

        //判断是否最后一个节点/是否驳回
        Integer detailCount = smsAssetMaterialProcurementApplyProcessDetailMapper.selectCount(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, allowReq.getApplyId()));
        if (detailCount.equals(processDetail.getProcessDetailSort()) || allowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_DENY) {
            is_done = true;//流程结束
            //修改申请表
            SmsAssetMaterialProcurementApply updateApply = new SmsAssetMaterialProcurementApply();
            updateApply.setId(allowReq.getApplyId());
            updateApply.setEndTime(nowDate);
            updateApply.setAllowStatus(allowReq.getProcessDetailStatus());
            smsAssetMaterialProcurementApplyMapper.updateById(updateApply);
        }

//        //流程结束且同意,预生成资产加入资产库
//        if (detailCount.equals(processDetail.getProcessDetailSort()) && allowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS) {
//            List<SmsAssetConsumableInStorageApplyGoods> goodsList =
//                    smsAssetConsumableInStorageApplyGoodsMapper.selectList(new LambdaQueryWrapper<SmsAssetConsumableInStorageApplyGoods>()
//                            .eq(SmsAssetConsumableInStorageApplyGoods::getApplyId, allowReq.getApplyId()));
//            if (goodsList != null && goodsList.size() > 0) {
//                for (SmsAssetConsumableInStorageApplyGoods goods : goodsList) {
//                    try {
//                        //根据物品生成资产id
//                        String categoryId = goods.getAssetCategory();
//                        //形成物品id
//                        String assetId = assetUtil.createAssetStorageID(categoryId,
//                                new Date(),
//                                IN_STORAGE_METHOD_CONSUMABLE_APPLY,
//                                inStorageApply.getApplySort());
//                        //创建物品(易耗品)
//                        SmsAssetConsumableStorage addAsset = new SmsAssetConsumableStorage();
//                        addAsset.setId(assetId);
//                        addAsset.setConsumableCategory(goods.getAssetCategory());
//                        addAsset.setConsumableNum(goods.getAssetNum());
//                        addAsset.setAddUserId(inStorageApply.getApplyUserId());
//                        addAsset.setConsumableStatus(ASSET_STATUS_IN_STORAGE);
//                        addAsset.setConsumableBrand(goods.getAssetBrand());
//                        addAsset.setConsumableModel(goods.getAssetModel());
//                        addAsset.setConsumableName(goods.getAssetName());
//                        addAsset.setConsumablePrice(goods.getAssetPrice());
//                        addAsset.setConsumableSupplier(inStorageApply.getApplySupplier());
//                        addAsset.setConsumableWarehouse(goods.getWarehouse());
//                        //设置总价
//                        Integer consumableNum = goods.getAssetNum();
//                        BigDecimal totalPrice = goods.getAssetPrice().multiply(BigDecimal.valueOf(consumableNum));
//                        addAsset.setTotalPrice(totalPrice);
//                        smsAssetConsumableStorageMapper.insert(addAsset);
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                        ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
//                    }
//                }
//            }
//        }

        //节点驳回 重置其余节点状态
        if (allowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_DENY) {
            SmsAssetMaterialProcurementApplyProcessDetail updateDenyDetail = new SmsAssetMaterialProcurementApplyProcessDetail();
            updateDenyDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_DENY_FINISH);
            smsAssetMaterialProcurementApplyProcessDetailMapper.update(updateDenyDetail, new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                    .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, allowReq.getApplyId())
                    .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        }

        //消息通知
        if (is_done) {//流程结束
            boolean result_status = false;//流程状态
            if (allowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowReq.getApplyId(), userId, result_status);
        } else {
            SmsAssetMaterialProcurementApplyProcessDetail nextDetail =
                    smsAssetMaterialProcurementApplyProcessDetailMapper.selectOne(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                            .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, allowReq.getApplyId())
                            .eq(SmsAssetMaterialProcurementApplyProcessDetail::getProcessDetailSort, processDetail.getProcessDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum;
            if (nextDetail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                if (nextDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                } else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                }
            }

            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessDetailObjectId());
            newTipsUtil.allowContinueTips(allowReq.getApplyId(),
                    userId,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Async
    public Future<ResponseResult> tableDownload(String applyId, HttpServletResponse response) {
        SmsAssetMaterialProcurementApply apply = smsAssetMaterialProcurementApplyMapper.selectById(applyId);
        //校验入库申请表是否存在
        if (apply == null || apply.getId() == null) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.ASSET_MATERIAL_PURCHASE_APPLY_NOT_EXIST));
        }
//        //如果申请表为“待审批”状态,进行阻断
//        if (apply.getAllowStatus() == AssetAllowStatusConstant.ASSET_ALLOW_STATUS_WAIT_ALLOW) {
//            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WORK_APPLICATION_DOWNLOAD_FAIL));
//        }
        //根据系统拼接下载路径
        String filePath = System.getProperty("os.name").toLowerCase().startsWith("win") ? fileSavePathConstant.getFILE_DOWNLOAD_PATH() : fileSavePathConstant.getFILE_DOWNLOAD_PATH_LINUX();

        String docFilePath = filePath + applyId + ".docx";
        String pdfFilePath = filePath + applyId + ".pdf";

        File pdfFile = new File(pdfFilePath);
        try {
            Map<String, Object> templateMap = new HashMap<>();
            List<String> picTagList = new ArrayList<>();

            templateMap.put("applyDepartment", filterResultNull(apply.getApplyDepartment()));
            templateMap.put("applyDate", TimeUtil.DateHanZiSimpleFormat(apply.getApplyDate()));
            templateMap.put("applyUser", filterResultNull(apply.getApplyPerson()));


            //获取审批流程
            List<SmsAssetMaterialProcurementApplyProcessDetail> processList = smsAssetMaterialProcurementApplyProcessDetailMapper.selectList(new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyProcessDetail>()
                    .eq(SmsAssetMaterialProcurementApplyProcessDetail::getApplyId, applyId));
            List<SmsCommonConsumableProcessEntity> processEntityList = new ArrayList<>();
            if (processList != null && processList.size() > 0) {
                for (SmsAssetMaterialProcurementApplyProcessDetail process : processList) {
                    if (process.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS || process.getProcessDetailStatus() == ASSET_ALLOW_STATUS_DENY) {
                        SmsCommonConsumableProcessEntity processEntity = new SmsCommonConsumableProcessEntity();

                        SmsUser smsUser = smsUserMapper.selectById(process.getAllowUserId());
                        if (smsUser != null) {
                            processEntity.setAllowUserName(smsUser.getRealName());
                        }

                        if (process.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS) {
                            processEntity.setAllowStatus("同意");
                        } else {
                            processEntity.setAllowStatus("拒绝");
                        }

                        //添加签名
                        if (isNullOrEmpty(process.getProcessDetailSign())) {
                            templateMap.put("allowSign", "");
                        } else {
                            String[] splitStr = process.getProcessDetailSign().split("=");
                            String fileName = splitStr[splitStr.length - 1];
                            File file = new File(filePath + fileName);
                            InputStream inputStream = new FileInputStream(file);
                            PictureRenderData pictures = Pictures.ofStream(inputStream, PictureType.PNG).size(60, 30).create();

                            processEntity.setAllowSign(pictures);

                            templateMap.put("allowSign", pictures);
                            picTagList.add("allowSign");
                        }

                        //添加印章
                        if (isNullOrEmpty(process.getProcessDetailStamp())) {
                            templateMap.put("allowStamp", "");
                        } else {
                            String[] splitStr = process.getProcessDetailStamp().split("=");
                            String fileName = splitStr[splitStr.length - 1];
                            File file = new File(filePath + fileName);
                            InputStream inputStream = new FileInputStream(file);
                            PictureRenderData pictures = Pictures.ofStream(inputStream,
                                    PictureType.PNG).size(60, 30).create();

                            processEntity.setAllowStamp(pictures);

                            templateMap.put("allowStamp", pictures);
                            picTagList.add("allowStamp");
                        }

                        processEntity.setAllowOpinion(filterResultNull(process.getProcessDetailRemark()));
                        if (process.getEndTime() != null) {
                            processEntity.setAllowTime(TimeUtil.DateHanZiSimpleFormat(process.getEndTime()));
                        }
                        processEntityList.add(processEntity);
                    }
                }
                if (processEntityList.size() > 0) {
                    templateMap.put("allowUserList", processEntityList);
                }
            }

            //封装物品信息
            List<SmsAssetMaterialProcurementApplyGoods> applyGoodsList = smsAssetMaterialProcurementApplyGoodsMapper.selectList(
                    new LambdaQueryWrapper<SmsAssetMaterialProcurementApplyGoods>().eq(SmsAssetMaterialProcurementApplyGoods::getApplyId, applyId));
            List<SmsMaterialProcurementGoodsResp> goodsList = new ArrayList<>();
            for (SmsAssetMaterialProcurementApplyGoods applyGoods : applyGoodsList) {
                SmsMaterialProcurementGoodsResp goods = new SmsMaterialProcurementGoodsResp();
                BeanUtils.copyProperties(applyGoods, goods);
                goods.setMaterialPlanNum(String.valueOf(applyGoods.getMaterialPlanNum()));
                goods.setMaterialRealNum(String.valueOf(applyGoods.getMaterialRealNum()));
                goods.setMaterialUseTime(TimeUtil.DateHanZiSimpleFormat(applyGoods.getMaterialUseTime()));
                goodsList.add(goods);
            }
            templateMap.put("goodsList", goodsList);

            ClassPathResource resource = new ClassPathResource("applyTemplates/materialProcurement.docx");
            InputStream is = resource.getInputStream();
            FileOutputStream outputStream = new FileOutputStream(docFilePath);

            XWPFTemplate template = XWPFTemplate.compile(is);

            //配置循环表格
            Configure config = template.getConfig();
            for (String tag : picTagList) {
                config.customPolicy(tag, new PictureRenderPolicy());
            }
            config.customPolicy("allowUserList", new LoopRowTableRenderPolicy());
            config.customPolicy("goodsList", new LoopRowTableRenderPolicy());

            template.render(templateMap);
            template.write(outputStream);

            is.close();
            outputStream.close();
            template.close();

            //word转pdf
            File destOri = new File(docFilePath);
            FileInputStream fileInputStream = new FileInputStream(destOri);
            FileOutputStream fileOutputStream = new FileOutputStream(pdfFilePath);

            Document document = new Document();
            document.loadFromStream(fileInputStream, FileFormat.Docx);
            //保存为PDF
            document.saveToFile(pdfFilePath, FileFormat.PDF);

            fileInputStream.close();
            fileOutputStream.close();
            document.close();

            log.debug("文件生成完成!");
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        try {
//            // 加载PDF文档
            PDDocument doc = PDDocument.load(pdfFile);
//            doc.setAllSecurityToBeRemoved(true);
//            // 创建水印
//            String watermark = "中国黄金";
//            PDPageContentStream contentStream;
//
//            for (PDPage page : doc.getPages()) {
//                contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);
//
//                //加载字体
//                ClassPathResource resource = new ClassPathResource("fonts/123.ttf");
//                InputStream is = resource.getInputStream();
//                PDFont font = PDType0Font.load(doc, is);
//
//                int startX = 0; // 起始位置 x 坐标
//                int startY = 0; // 起始位置 y 坐标
//                float angle = -45; // 角度
//                float interval = 220; // 间隔
//                float opacity = 0.3f; // 透明度
//                int colorR = 127; // 颜色 red 值
//                int colorG = 127; // 颜色 green 值
//                int colorB = 127; // 颜色 blue 值
//
//                //透明的
//                PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
//                r0.setNonStrokingAlphaConstant(opacity);
//                r0.setAlphaSourceFlag(true);
//                contentStream.setGraphicsStateParameters(r0);
//
//                //水印颜色
//                contentStream.setNonStrokingColor(colorR, colorG, colorB);
//                contentStream.beginText();
//                contentStream.setFont(font, 30f);
//
//                int xTimes = (int) Math.ceil(page.getMediaBox().getWidth() / interval);
//                int yTimes = (int) Math.ceil(page.getMediaBox().getHeight() / interval);
//                for (int x = startX; x <= xTimes; x++) {
//                    for (int y = startY; y <= yTimes; y++) {
//                        contentStream.setTextRotation(angle, (x * interval), (y * interval));
//                        contentStream.showText(watermark);
//                    }
//                }
//                contentStream.endText();
//                contentStream.restoreGraphicsState();
//                contentStream.close();
//                is.close();
//            }


            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.pdf;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("物资采购申请表预览.pdf", "utf-8"));
            response.setHeader("file-type", "download");
            response.setHeader("file-name", URLEncoder.encode("物资采购申请表预览.pdf", "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
            //刷新缓冲
            response.flushBuffer();

            // 保存PDF文档
            doc.save(response.getOutputStream());
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));

        }
        return null;
    }

    @Override
    public ResponseResult getMaterialProcurementApplyAllList(Integer allowStatus, String applyName, Integer pageNum, Integer pageSize) {
        Page<SmsAssetMaterialProcurementApply> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsAssetMaterialProcurementApply> materialProcurementApplyLambdaQueryWrapper = new LambdaQueryWrapper<SmsAssetMaterialProcurementApply>()
                .orderByDesc(SmsAssetMaterialProcurementApply::getCreateTime);
        if (!isNullOrEmpty(applyName)) {
            List<String> userIdList = smsUserMapper.selectList(new LambdaQueryWrapper<SmsUser>()
                            .like(SmsUser::getRealName, applyName))
                    .stream()
                    .map(SmsUser::getId)
                    .collect(Collectors.toList());
            if (!userIdList.isEmpty()) {
                materialProcurementApplyLambdaQueryWrapper.in(SmsAssetMaterialProcurementApply::getApplyUserId, userIdList);
            }else {
                materialProcurementApplyLambdaQueryWrapper.eq(SmsAssetMaterialProcurementApply::getApplyUserId, "");
            }
            materialProcurementApplyLambdaQueryWrapper.and(i -> {
                        i.like(SmsAssetMaterialProcurementApply::getApplyPerson, applyName)
                        .or()
                        .like(SmsAssetMaterialProcurementApply::getApplyDepartment, applyName);
            });
        }
        if (!isNullOrEmpty(allowStatus)) {
            materialProcurementApplyLambdaQueryWrapper.eq(SmsAssetMaterialProcurementApply::getAllowStatus,allowStatus);
        }
        //构造回传数据
        smsAssetMaterialProcurementApplyMapper.selectPage(page,materialProcurementApplyLambdaQueryWrapper);
        List<SmsAssetMaterialProcurementApplyResp> respList = page.getRecords().stream().map(apply -> {
                SmsAssetMaterialProcurementApplyResp applyResp = new SmsAssetMaterialProcurementApplyResp();
                BeanUtils.copyProperties(apply, applyResp);
                applyResp.setId(apply.getId());
                //获取当前用户信息并进行设置
                SmsUser smsUser = cacheUtil.getUserInfo(apply.getApplyUserId());
                SmsSearchUserResp userResp = new SmsSearchUserResp();
                if (smsUser != null) {
                    BeanUtils.copyProperties(smsUser, userResp);
                }
                applyResp.setApplyUserInfo(userResp);
                return applyResp;
            }).collect(Collectors.toList());
            int total = (int) page.getTotal();
        return CommonResult.success(respList, total);
    }

    private String filterResultNull(String resultStr) {
        if (resultStr == null || resultStr.equals("null")) {
            return "";
        }
        return resultStr;
    }
}
